#include "stdafx.h"
#include "TreeView.h"

TreeItem::TreeItem()
	: is_expansion_(false)
	, size_(0, 0)
	, parent_(NULL)
	, font_(std::wstring(L"Arial"), 14)
{
	chadren_.clear();
}

TreeItem::~TreeItem()
{

}

void TreeItem::paint(SkCanvas* canvas)
{
	paintItem(canvas);
	paintChildren(canvas);
}

void TreeItem::paintItem(SkCanvas* canvas)
{
	if (parent_.get() == NULL)
	{
		// ATLTRACE("[%s][%d]\r\n", __FUNCTION__, __LINE__);
		canvas->FillRect(SkColor(0, 78, 128), 0, 0, size_.width(), size_.height());
		canvas->drawText(str_, font_, SkColor(200, 200, 200), 0, 0, size_.width(), size_.height());
		canvas->drawLine(SkColor(0, 0, 0), 0, size_.height() - 1, size_.width(), size_.height() - 1);

	}
	else
	{
		canvas->FillRect(SkColor(0, 100, 100), 0, 0, size_.width(), size_.height());
		//static SkFont font2(std::wstring(L"����"), 10);
		font_.setFontSize(8);
		canvas->drawText(str_, font_, SkColor(200, 200, 200), 0, 0, size_.width(), size_.height());
		canvas->drawLine(SkColor(0, 0, 0), 0, size_.height() - 1, size_.width(), size_.height() - 1);
	}
}

void TreeItem::paintChildren(SkCanvas* canvas)
{
	if (is_expansion_)
	{
		int yPos = size_.height();
		for (std::list<std::shared_ptr<TreeItem>>::iterator iter = chadren_.begin(); iter != chadren_.end(); ++iter)
		{
			if ((*iter).get())
			{
				canvas->save();

				canvas->translate(0, yPos);
				(*iter)->paint(canvas);
				canvas->restore();
				yPos += (*iter)->getHeightWithChildren();
			}
		}
	}
}


int TreeItem::getHeightWithChildren()
{
	int children_lengh = size_.height();
	if (is_expansion_)
	{
		for (std::list<std::shared_ptr<TreeItem>>::iterator iter = chadren_.begin();
			iter != chadren_.end(); ++iter)
		{
			children_lengh += (*iter)->getHeightWithChildren();
		}
	}

	return children_lengh;
}

bool TreeItem::hasChildren()
{
	return chadren_.size() != 0;
}


bool TreeItem::updateLayout()
{
	for (std::list<std::shared_ptr<TreeItem>>::iterator iter = chadren_.begin(); iter != chadren_.end(); ++iter)
	{
		(*iter)->size_.set_width(size_.width());
	}

	return true;
}

TreeItem* TreeItem::getItemByPos(gfx::Point pos)
{
	if (pos.y() >= 0 && pos.y() < size_.height())
	{
		return this;
	}

	int yPos = size_.height();
	for (std::list<std::shared_ptr<TreeItem>>::iterator iter = chadren_.begin();
		iter != chadren_.end(); ++iter)
	{
		gfx::Point child_pos;
		child_pos.set_x(pos.x());
		child_pos.set_y(pos.y() - yPos);
		TreeItem* item = (*iter)->getItemByPos(child_pos);
		if (item)
		{
			return item;
		}

		yPos += (*iter)->getHeightWithChildren();
	}

	return NULL;
}


TreeView::TreeView(View* parent)
	: View(parent)
	, show_pos_(0)
{
}


TreeView::~TreeView()
{
}

std::shared_ptr<TreeItem> TreeView::AddString(std::wstring str, std::shared_ptr<TreeItem> parent_item)
{
	std::shared_ptr<TreeItem> new_item = std::shared_ptr<TreeItem>(new TreeItem);
	new_item->size_.set_height(24);
	new_item->size_.set_width(Width());
	new_item->str_ = str;
	new_item->parent_ = parent_item;

	if (parent_item.get())
	{
		parent_item->chadren_.push_back(new_item);
	} 
	else
	{
		items_.push_back(new_item);
	}

	updateView();

	return new_item;
}

bool TreeView::paint(SkCanvas* canvas)
{
	paintBackground(canvas);
	if (getStatus() == STATUS_FOCUS)
	{
		paintFocus(canvas);
	}
	else
	{
		paintBorder(canvas);

	}


	canvas->save();
	if (canvas->clipRect(1, 1, Width() - 2, Height() - 2))
	{
		canvas->translate(1, 1);
		canvas->translate(0, 0 - show_pos_);

		paintFrontground(canvas);
	}
	canvas->restore();

	return true;

}

bool TreeView::paintBackground(SkCanvas* canvas)
{
	if (canvas)
	{
		canvas->FillRect(SkColor(50, 50, 50), 0, 0, Width(), Height());
		return true;
	}
	return false;

}

bool TreeView::paintFrontground(SkCanvas* canvas)
{
	int yPos = 0;
	for (std::list<std::shared_ptr<TreeItem>>::iterator iter = items_.begin(); iter != items_.end(); ++iter)
	{
		canvas->save();
		canvas->translate(0, yPos);
		(*iter)->paint(canvas);
		canvas->restore();

		yPos += (*iter)->getHeightWithChildren();

	}
	return true;
}

int TreeView::getScrollHight()
{

	int yPos = 0;
	for (std::list<std::shared_ptr<TreeItem>>::iterator iter = items_.begin(); iter != items_.end(); ++iter)
	{
		yPos += (*iter)->getHeightWithChildren();

	}

	return yPos;
}

void TreeView::goToPos(int pos)
{
	show_pos_ = pos;
	if (show_pos_ < 0)
	{
		show_pos_ = 0;
	}

	if (show_pos_ > getScrollHight() - 10)
	{
		show_pos_ = getScrollHight() - 10;
	}
	updateView();
}

bool TreeView::updateLayout()
{
	for (std::list<std::shared_ptr<TreeItem>>::iterator iter = items_.begin(); iter != items_.end(); ++iter)
	{
		(*iter)->size_.set_width(Width() - 3 );
		(*iter)->updateLayout();
	}

	return true;
}

bool TreeView::processMouseEvent(MouseEvent& event)
{
	if (event.type == TYPE_TOUCH_WHEEL)
	{
		int n = event.param / WHEEL_DELTA;
		show_pos_ -= (n * 20);

		fixShowPos();

		updateView();
		return true;
	}
	else if (event.type == TYPE_TOUCH_DCLICK)
	{
		gfx::Point point;
		point.set_x(event.x - X());
		point.set_y(event.y - Y());
		gfx::Point pos;
		PointToPos(point, pos);
		ATLTRACE(L"pos [%d, %d]\r\n", pos.x(), pos.y());

		TreeItem* item = getItemByPos(pos);
		if (item)
		{
			item->is_expansion_ = !item->is_expansion_;
		}

		fixShowPos();

		updateView();
	}

	return false;
}

void TreeView::PointToPos(gfx::Point point, gfx::Point& pos)
{
	pos = point;
	pos.set_y(pos.y() + show_pos_);
}

TreeItem* TreeView::getItemByPos(gfx::Point pos)
{
	int yPos = 0;
	for (std::list<std::shared_ptr<TreeItem>>::iterator iter = items_.begin();
		iter != items_.end(); ++iter)
	{ 
		int item_bottom = (*iter)->getHeightWithChildren() + yPos;
		if (pos.y() >= yPos && pos.y() < item_bottom)
		{
			gfx::Point child_pos;
			child_pos.set_x(pos.x());
			child_pos.set_y(pos.y() - yPos);
			TreeItem* item = (*iter)->getItemByPos(child_pos);
			return item;
		}

		yPos = item_bottom;
	}

	return NULL;
}

void TreeView::fixShowPos()
{
	if (show_pos_ > static_cast<int>(getScrollHight() - Height()))
	{
		show_pos_ = static_cast<int>(getScrollHight() - Height());
	}

	if (show_pos_ < 0)
	{
		show_pos_ = 0;
	}

}